<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>柯里化函数</title>
  </head>
  <body></body>

  <script>
    // 定义：在数学和计算机科学中，柯里化是一种将使用多个参数的一个函数转换成一系列使用一个参数的函数的技术。
    // 柯里化函数：预先处理的思想（闭包机制）

    // 例子：
    function add(a, b) {
      return a + b;
    }
    let sum1 = add(1, 2);

    // 转换为柯里化函数
    function addCurrying(a) {
      return function (b) {
        return a + b;
      };
    }
    let sum2 = addCurrying(1)(2);

    // 应用场景：减少重复参数传递
    // 需求：创建五十个 url 地址，但 30 个协议相同，25 个域名相同

    // 常规写法
    function simpleURL(protocol, domain, path) {
      return protocol + "://" + domain + "/" + path;
    }
    {
      const url1 = simpleURL("http", "mysite", "index.html");
      const url2 = simpleURL("http", "mysite", "news.html");
      const url3 = simpleURL("http", "mysite", "mine.html");
      const url4 = simpleURL("https", "others", "home.html");

      console.log(url1, url2, url3, url4);
    }

    // 柯里化处理
    // 将多个函数的形参拆分到不同的返回值函数，这个结果叫做柯里化函数
    function currySimpleURL(protocol) {
      return function (domain) {
        return function (path) {
          return protocol + "://" + domain + "/" + path;
        };
      };
    }

    {
      let createUrlWithHttpStart = currySimpleURL("http");
      let createUrlWithMySiteStart = createUrlWithHttpStart("mysite");

      const url1 = createUrlWithMySiteStart("index.html");
      const url2 = createUrlWithMySiteStart("news.html");
      const url3 = createUrlWithMySiteStart("mine.html");
      const url4 = currySimpleURL("https")("others")("home.html");

      console.log(url1, url2, url3, url4);
    }

    // 声明一个函数，能够将任意多参数函数转换为柯里化函数，允许将多个参数分次传入执行
    function curry(fn, ...args1) {
      return function (...args2) {
        let args = args1.concat(args2);
        return fn.apply(null, args);
      };
    }

    {
      let createUrlWithHttpStart = curry(simpleURL, "http");
      let url = createUrlWithHttpStart("mysite", "myfile.js");
      console.log(url);
    }
  </script>
</html>
